package com.ysd.lis.service.lab.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.ysd.common.Result;
import com.ysd.lis.dto.UploadCipherText;
import com.ysd.lis.entity.SysInterface;
import com.ysd.lis.entity.lab.LabChannel;
import com.ysd.lis.entity.lab.LabInstrSetup;
import com.ysd.lis.entity.lab.LabRptGroup;
import com.ysd.lis.entity.qc.QcInstrItemRule;
import com.ysd.lis.entity.qc.QcRule;
import com.ysd.lis.entity.sta.StaInstrSetup;
import com.ysd.lis.entity.sta.StaInstrSetupLog;
import com.ysd.lis.entity.sta.StaModule;
import com.ysd.lis.mapper.lab.LabInstrSetupMapper;
import com.ysd.lis.mapper.qc.QcInstrItemRuleMapper;
import com.ysd.lis.mapper.qc.QcRuleMapper;
import com.ysd.lis.mapper.sys.SysInterfaceMapper;
import com.ysd.lis.request.AddInstrSetupParam;
import com.ysd.lis.request.DeleteParam;
import com.ysd.lis.request.InstrSetupPageParam;
import com.ysd.lis.request.lab.LabInstrChannelVo;
import com.ysd.lis.service.lab.LabInstrSetupService;
import com.ysd.lis.service.lab.LabRptGroupService;
import com.ysd.lis.service.sta.StaInstrSetupLogService;
import com.ysd.lis.service.sta.StaInstrSetupService;
import com.ysd.util.AESUtils;
import com.ysd.util.RedisUserManager;
import com.ysd.util.ToolsUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author bai
 * @since 2023-12-09
 */
@Service
public class LabInstrSetupServiceImpl extends ServiceImpl<LabInstrSetupMapper, LabInstrSetup> implements LabInstrSetupService {

    @Autowired
    private LabInstrSetupMapper labInstrSetupMapper;
    @Autowired
    private LabInstrSetupService labInstrSetupService;
    @Autowired
    private LabRptGroupService rptGroupService;

    @Autowired
    SysInterfaceMapper sysInterfaceMapper;
    @Autowired
    StaInstrSetupLogService staInstrSetupLogService;

    @Autowired
    StaInstrSetupService staInstrSetupService;

    @Override
    public Result findLabInstrSetup(InstrSetupPageParam instrSetupPageParam) {
        MPJLambdaWrapper<LabInstrSetup> lambdaQueryWrapper = new MPJLambdaWrapper<>();


        lambdaQueryWrapper.selectAll(LabInstrSetup.class)
                .selectAs("ld", LabRptGroup::getRptGroupName, LabInstrSetup::getReportGroupName)
                .leftJoin(LabRptGroup.class, "ld", LabRptGroup::getRptGroup, LabInstrSetup::getRptGroup).eq(LabInstrSetup::getDelFlag, 0);
        if (ToolsUtils.isNotEmpty(instrSetupPageParam.getWorkGroup())) {
            lambdaQueryWrapper.eq(LabInstrSetup::getWorkGroup, instrSetupPageParam.getWorkGroup());
        }
        if (ToolsUtils.isNotEmpty(instrSetupPageParam.getInstrClass())) {
            lambdaQueryWrapper.eq(LabInstrSetup::getInstrClass, instrSetupPageParam.getInstrClass());
        }
        if (ToolsUtils.isNotEmpty(instrSetupPageParam.getInstrName())) {
            lambdaQueryWrapper.like(LabInstrSetup::getInstrName, instrSetupPageParam.getInstrName());
        }
        if(ToolsUtils.isNotEmpty(instrSetupPageParam.getPoct())){
            lambdaQueryWrapper.eq(LabInstrSetup::getPoct, instrSetupPageParam.getPoct());
        }
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(instrSetupPageParam.getOrgId()), LabInstrSetup::getOrgId, instrSetupPageParam.getOrgId());
        List<LabInstrSetup> labInstrSetups = labInstrSetupMapper.selectList(lambdaQueryWrapper);
        return Result.succ(labInstrSetups);
    }

    @Override
    public Result findLabInstrSetupList(String rptGroupId) {
        MPJLambdaWrapper<LabInstrSetup> mpjLambdaWrapper = new MPJLambdaWrapper<>();
        mpjLambdaWrapper.selectAll(LabInstrSetup.class).selectAs("LRG", LabRptGroup::getRptGroupName, LabInstrSetup::getReportGroupName).leftJoin(LabRptGroup.class, "LRG", LabRptGroup::getRptGroup, LabInstrSetup::getRptGroup);
        mpjLambdaWrapper.eq(LabInstrSetup::getDelFlag, 0);
        if (StringUtils.isNotBlank(rptGroupId)) {
            mpjLambdaWrapper.eq(LabInstrSetup::getRptGroup, rptGroupId);
        }
        List<LabInstrSetup> labInstrSetups = labInstrSetupMapper.selectList(mpjLambdaWrapper);
        return Result.succ(1, "查询成功", labInstrSetups);
    }

    @Override
    public Result findInstrSetupAndChannelList(String rptGroupId, String itemNo) {
        MPJLambdaWrapper<LabInstrSetup> mpjLambdaWrapper = new MPJLambdaWrapper<>();
        mpjLambdaWrapper.selectAll(LabInstrChannelVo.class);
        mpjLambdaWrapper.selectAs("LRG", LabRptGroup::getRptGroupName, LabInstrChannelVo::getReportGroupName);
        mpjLambdaWrapper.selectAs("LC", LabChannel::getChannelCode, LabInstrChannelVo::getChannelCode);
        mpjLambdaWrapper.leftJoin(LabRptGroup.class, "LRG", LabRptGroup::getRptGroup, LabInstrSetup::getRptGroup);
        mpjLambdaWrapper.leftJoin(LabChannel.class, "LC", on -> on.eq(LabChannel::getInstrCode, LabInstrSetup::getInstrCode).eq(LabChannel::getRptGroup, rptGroupId).eq(LabChannel::getItemNo, itemNo).eq(LabChannel::getDelFlag, 0));
        mpjLambdaWrapper.and(wrapper -> wrapper.eq(LabChannel::getIsStop, "0").or().isNull(LabChannel::getIsStop));
        mpjLambdaWrapper.eq(LabInstrSetup::getDelFlag, 0);
        if (StringUtils.isNotBlank(rptGroupId)) {
            mpjLambdaWrapper.eq(LabInstrSetup::getRptGroup, rptGroupId);
        }
        List<LabInstrChannelVo> labInstrSetups = labInstrSetupMapper.selectJoinList(LabInstrChannelVo.class, mpjLambdaWrapper);
        return Result.succ(1, "查询成功", labInstrSetups);
    }

    @Autowired
    QcRuleMapper qcRuleMapper;
    @Autowired
    QcInstrItemRuleMapper qcInstrItemRuleMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result addLabInstrSetup(AddInstrSetupParam addInstrSetupParam) {
        LabInstrSetup labInstrSetup = new LabInstrSetup();
        BeanUtil.copyProperties(addInstrSetupParam, labInstrSetup);
        boolean save = this.save(labInstrSetup);
        if (save) {
            // 查看是否是质控仪器，如果是质控仪器则添加仪器质控规则
            Boolean isQc = labInstrSetup.getIsQc();
            if (isQc) {
                AddQcInstrItemRule(labInstrSetup);
            }
            return Result.succ(1, "添加成功！", labInstrSetup);
        } else {
            return Result.fail("添加失败！");
        }
    }


    @Override
    public Result editLabInstrSetup(AddInstrSetupParam addInstrSetupParam) {
        LabInstrSetup labInstrSetup = new LabInstrSetup();
        BeanUtil.copyProperties(addInstrSetupParam, labInstrSetup);
        boolean b = this.updateById(labInstrSetup);
        if (b) {
            // 查看是否是质控仪器，如果是质控仪器则添加仪器质控规则
            Boolean isQc = labInstrSetup.getIsQc();
            if (isQc) {
                // 查看此仪器下是否有质控规则 如果没有则添加
                LambdaQueryWrapper<QcInstrItemRule> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(QcInstrItemRule::getDelFlag, 0).eq(QcInstrItemRule::getPid, labInstrSetup.getId());
                Integer cnt = qcInstrItemRuleMapper.selectCount(queryWrapper);
                if (cnt <= 0) {
                    AddQcInstrItemRule(labInstrSetup);
                }
            }
            return Result.succ(1, "编辑成功！", labInstrSetup);
        } else {
            return Result.fail("编辑失败！");
        }
    }

    @Override
    public Result deleteLabInstrSetup(DeleteParam deleteParam) {
        if (ToolsUtils.isEmpty(deleteParam)) {
            return Result.fail("入参不可为空！");
        }
        if (ToolsUtils.isEmpty(deleteParam.getIds())) {
            return Result.fail("入参不可为空！");
        }
        String ids = deleteParam.getIds();
        String[] array = ids.split(",");

        for (int i = 0; i < array.length; i++) {
            LambdaUpdateWrapper<LabInstrSetup> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.eq(LabInstrSetup::getId, array[i]);
            lambdaUpdateWrapper.set(LabInstrSetup::getDelFlag, 1);
            boolean b = this.update(null, lambdaUpdateWrapper);
            if (!b) {
                return Result.fail("删除失败！");
            }
        }

        return Result.succ(1, "删除成功！", null);
    }

    @Override
    public Result getInstrSetupList(InstrSetupPageParam instrSetupPageParam) {
        LambdaQueryWrapper<LabInstrSetup> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(LabInstrSetup::getDelFlag, 0);
        if (ToolsUtils.isNotEmpty(instrSetupPageParam.getWorkGroup())) {
            lambdaQueryWrapper.eq(LabInstrSetup::getWorkGroup, instrSetupPageParam.getWorkGroup());
        }
        if (ToolsUtils.isNotEmpty(instrSetupPageParam.getInstrClass())) {
            lambdaQueryWrapper.eq(LabInstrSetup::getInstrClass, instrSetupPageParam.getInstrClass());
        }
        if (ToolsUtils.isNotEmpty(instrSetupPageParam.getInstrName())) {
            lambdaQueryWrapper.like(LabInstrSetup::getInstrName, instrSetupPageParam.getInstrName());
        }
        if (ToolsUtils.isNotEmpty(instrSetupPageParam.getPoct())) {
            lambdaQueryWrapper.eq(LabInstrSetup::getPoct, instrSetupPageParam.getPoct());
        }
        List<LabInstrSetup> instrSetupList = labInstrSetupMapper.selectList(lambdaQueryWrapper);

        return Result.succ(instrSetupList);
    }

    @Override
    public LabInstrSetup findRptGroupByInstrCode(String instrCode, String orgId) {
        LambdaQueryWrapper<LabInstrSetup> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(LabInstrSetup::getDelFlag, 0);
        lambdaQueryWrapper.eq(LabInstrSetup::getInstrCode, instrCode);
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(orgId), LabInstrSetup::getOrgId, orgId);
        List<LabInstrSetup> instrSetupList = labInstrSetupMapper.selectList(lambdaQueryWrapper);
        return CollectionUtils.isEmpty(instrSetupList) ? null : instrSetupList.get(0);
    }

    @Override
    public Result syncInstrs() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        String token = request.getHeader("Authorization").replace("Bearer ", "");
        String orgId = RedisUserManager.getStoreOrg("currentOrg" + token);

        LambdaQueryWrapper<SysInterface> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysInterface::getDelFlag, 0);
        wrapper.eq(SysInterface::getIsEnable, 1);
        List<SysInterface> sysInterfaces = sysInterfaceMapper.selectList(wrapper);
        List<String> collect = sysInterfaces.stream().filter(o -> Objects.nonNull(o) && StringUtils.isNotBlank(o.getInterfaceUrl())).map(SysInterface::getInterfaceUrl).distinct().collect(Collectors.toList());

        try {
            if (CollectionUtils.isNotEmpty(collect)) {
                for (String webUrl : collect) {
                    LabInstrSetup labInstrSetup = new LabInstrSetup();
                    labInstrSetup.setOrgId(orgId);
                    String returnMsg1 = HttpUtil.createPost(webUrl + "/public/syncInstrs").body(JSONUtil.toJsonStr(labInstrSetup)).contentType("application/json").execute().body();
                    JSONObject jsonObject = new JSONObject(returnMsg1);
                    JSONObject status = jsonObject.getJSONObject("status");
                    String code = status.get("code").toString();
                    if ("400".equals(code)) {
                        return Result.fail("接口管理平台异常,请检查");
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("接口管理平台异常,请检查");
        }
        return Result.succ(1, "请求成功", null);
    }


    private void AddQcInstrItemRule(LabInstrSetup labInstrSetup) {

        // 获取质控规则列表
        List<String> ruleCodes = new ArrayList<>();
        ruleCodes.add("1-2s");
        ruleCodes.add("1-3s");
        ruleCodes.add("2-2s");
        ruleCodes.add("3-1s");
        ruleCodes.add("R4s");
        ruleCodes.add("10x");
        LambdaQueryWrapper<QcRule> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(QcRule::getDelFlag, 0);
        lambdaQueryWrapper.in(QcRule::getCode, ruleCodes);
        List<QcRule> qcRules = qcRuleMapper.selectList(lambdaQueryWrapper);


        QcInstrItemRule rule = new QcInstrItemRule();
        rule.setEnableDate(DateUtil.beginOfDay(new Date()).toTimestamp());
        rule.setIsAlarm(false);
        rule.setIsOutControl(false);
        rule.setPid(labInstrSetup.getId());
        rule.setPtype("1");
        if (CollectionUtils.isNotEmpty(qcRules)) {
            List<String> ruleIds = qcRules.stream().map(QcRule::getId).collect(Collectors.toList());
            StringBuffer s = new StringBuffer();
            for (int i = 0; i < ruleIds.size(); i++) {
                s.append(ruleIds.get(i));
                if (i < ruleIds.size() - 1) {
                    s.append(",");
                }
            }
            rule.setRuleIds(s.toString());
        }
        rule.setRuleType("Westgard");
        rule.setSeq(1);
        qcInstrItemRuleMapper.insert(rule);

    }


    @Override
    public Result findStaInsterLogList() {
        List<StaInstrSetupLog> list = staInstrSetupLogService.list(new LambdaQueryWrapper<StaInstrSetupLog>().eq(StaInstrSetupLog::getDelFlag, 0).orderByDesc(StaInstrSetupLog::getCreateTime));
        return Result.succ(1, "查询成功", list);
    }


    @Override
    public Result uploadRegisterFile(MultipartFile file, HttpServletRequest request) throws Exception {
        if (file == null) {
            return Result.fail("上传信息不能为空");
        }
        String privateKey = null;
        List<String> modulCodes = new ArrayList<>();
        List<String> codeList = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
            String line;
            while ((line = br.readLine()) != null) {
                if (line.contains("-----BEGIN PRIVATE KEY-----")) {
                    privateKey = br.readLine(); // 读取私钥内容
                    br.readLine(); // 跳过 "-----END PRIVATE KEY-----"
                } else {
                    modulCodes.add(line);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        List<String> modulCodeList = modulCodes.stream().filter(StringUtils::isNotBlank).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(modulCodeList)) {
            return Result.fail("未找到注册编码");
        }

        List<String> failedList = new ArrayList<>();
        Map<String, String> decryptMap = new HashMap<>();
        for (String modulCode : modulCodeList) {
            String decrypt = AESUtils.decrypt(modulCode);
            if (StringUtils.isNotBlank(decrypt)) {
                codeList.add(decrypt);
                decryptMap.put(decrypt, modulCode);
            } else {
                failedList.add(modulCode);
            }
        }
        List<StaInstrSetupLog> logModules = new ArrayList<>();
        for (String fail : failedList) {
            StaInstrSetupLog moduleLog = new StaInstrSetupLog();
            moduleLog.setState("0");
            moduleLog.setInstrRegister(fail);
            logModules.add(moduleLog);
        }
        staInstrSetupLogService.saveBatch(logModules);
        if (CollectionUtil.isEmpty(codeList)) {
            return Result.fail("解密失败");
        }
        MPJLambdaWrapper<StaInstrSetup> lambdaQueryWrapper = new MPJLambdaWrapper<>();
        lambdaQueryWrapper.eq(StaInstrSetup::getDelFlag, 0);
        lambdaQueryWrapper.in(StaInstrSetup::getStaInstrCode, codeList);
        List<StaInstrSetup> staInstrSetups = staInstrSetupService.list(lambdaQueryWrapper);
        List<String> instrCodes = staInstrSetups.stream().filter(item -> StringUtils.isNotBlank(item.getStaInstrCode())).map(StaInstrSetup::getStaInstrCode).collect(Collectors.toList());

        List<StaInstrSetupLog> noSetUpList = new ArrayList<>();
        // 找出 codeList 中不在 staModules 中的 modCode
        List<String> missingModCodes = codeList.stream()
                .filter(modCode -> !instrCodes.contains(modCode))
                .collect(Collectors.toList());
        for (String missingModCode : missingModCodes) {
            StaInstrSetupLog moduleLog = new StaInstrSetupLog();
            moduleLog.setStaInstrCode(missingModCode);
            moduleLog.setState("0");
            moduleLog.setInstrRegister(decryptMap.get(missingModCode));
            noSetUpList.add(moduleLog);
        }
        staInstrSetupLogService.saveBatch(noSetUpList);
        for (StaInstrSetup staInstrSetup : staInstrSetups) {
            LabInstrSetup labInstrSetup = new LabInstrSetup();
            StaInstrSetupLog staInstrSetupLog = new StaInstrSetupLog();
            BeanUtil.copyProperties(staInstrSetup, labInstrSetup, "id");
            BeanUtil.copyProperties(staInstrSetup, staInstrSetupLog, "id");
            staInstrSetupLog.setState("1");
            staInstrSetupLog.setInstrRegister(decryptMap.get(staInstrSetup.getStaInstrCode()));
            staInstrSetupLogService.saveOrUpdate(staInstrSetupLog, new LambdaQueryWrapper<StaInstrSetupLog>().eq(StaInstrSetupLog::getInstrCode, staInstrSetupLog.getInstrCode()));
            labInstrSetupService.saveOrUpdate(labInstrSetup, new LambdaQueryWrapper<LabInstrSetup>().eq(LabInstrSetup::getInstrCode, staInstrSetup.getInstrCode()));
        }
        return Result.succ(1, "上传成功", "");
    }

    @Override
    public Result uploadRegisterCipherText(UploadCipherText uploadCipherText) throws Exception {
        String cipherText = uploadCipherText.getCipherText();
        cipherText = cipherText.replaceAll("\\s+", "");
        List<String> codeList = new ArrayList<>();
        List<String> failedList = new ArrayList<>();
        Map<String, String> decryptMap = new HashMap<>();
        String decrypt = AESUtils.decrypt(cipherText);
        if (StringUtils.isNotBlank(decrypt)) {
            codeList.add(decrypt);
            decryptMap.put(decrypt, cipherText);
        } else {
            failedList.add(cipherText);
        }

        List<StaInstrSetupLog> logModules = new ArrayList<>();
        for (String fail : failedList) {
            StaInstrSetupLog moduleLog = new StaInstrSetupLog();
            moduleLog.setState("0");
            moduleLog.setInstrRegister(fail);
            logModules.add(moduleLog);
        }
        staInstrSetupLogService.saveBatch(logModules);
        if (CollectionUtil.isEmpty(codeList)) {
            return Result.fail("解密失败");
        }
        MPJLambdaWrapper<StaInstrSetup> lambdaQueryWrapper = new MPJLambdaWrapper<>();
        lambdaQueryWrapper.eq(StaInstrSetup::getDelFlag, 0);
        lambdaQueryWrapper.in(StaInstrSetup::getStaInstrCode, codeList);
        List<StaInstrSetup> staInstrSetups = staInstrSetupService.list(lambdaQueryWrapper);
        List<String> instrCodes = staInstrSetups.stream().filter(item -> StringUtils.isNotBlank(item.getStaInstrCode())).map(StaInstrSetup::getStaInstrCode).collect(Collectors.toList());

        List<StaInstrSetupLog> noSetUpList = new ArrayList<>();
        // 找出 codeList 中不在 staModules 中的 modCode
        List<String> missingModCodes = codeList.stream()
                .filter(modCode -> !instrCodes.contains(modCode))
                .collect(Collectors.toList());
        for (String missingModCode : missingModCodes) {
            StaInstrSetupLog moduleLog = new StaInstrSetupLog();
            moduleLog.setStaInstrCode(missingModCode);
            moduleLog.setState("0");
            moduleLog.setInstrRegister(decryptMap.get(missingModCode));
            noSetUpList.add(moduleLog);
        }
        staInstrSetupLogService.saveBatch(noSetUpList);
        for (StaInstrSetup staInstrSetup : staInstrSetups) {
            LabInstrSetup labInstrSetup = new LabInstrSetup();
            StaInstrSetupLog staInstrSetupLog = new StaInstrSetupLog();
            BeanUtil.copyProperties(staInstrSetup, labInstrSetup, "id");
            BeanUtil.copyProperties(staInstrSetup, staInstrSetupLog, "id");
            staInstrSetupLog.setState("1");
            staInstrSetupLog.setInstrRegister(decryptMap.get(staInstrSetup.getStaInstrCode()));
            staInstrSetupLogService.saveOrUpdate(staInstrSetupLog, new LambdaQueryWrapper<StaInstrSetupLog>().eq(StaInstrSetupLog::getInstrCode, staInstrSetupLog.getInstrCode()));
            labInstrSetupService.saveOrUpdate(labInstrSetup, new LambdaQueryWrapper<LabInstrSetup>().eq(LabInstrSetup::getInstrCode, staInstrSetup.getInstrCode()));
        }
        return Result.succ(1, "上传成功", "");
    }
}
